<!DOCTYPE html>
<html lang="en-us">
  <head>

    <meta http-equiv="content-type" content="text/html; charset=utf-8">
    
<meta charset="UTF-8">
<title>SAML without Kibana | Elasticsearch Guide [7.7] | Elastic</title>
<link rel="home" href="index.html" title="Elasticsearch Guide [7.7]">
<link rel="up" href="saml-guide.html" title="Configuring SAML single-sign-on on the Elastic Stack">
<link rel="prev" href="saml-troubleshooting.html" title="Troubleshooting SAML Realm Configuration">
<link rel="next" href="oidc-guide.html" title="Configuring single sign-on to the Elastic Stack using OpenID Connect">
<meta name="DC.type" content="Learn/Docs/Elasticsearch/Reference/7.7">
<meta name="DC.subject" content="Elasticsearch">
<meta name="DC.identifier" content="7.7">
<meta name="robots" content="noindex,nofollow">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <script src="https://cdn.optimizely.com/js/18132920325.js"></script>
    <link rel="apple-touch-icon" sizes="57x57" href="/apple-icon-57x57.png">
    <link rel="apple-touch-icon" sizes="60x60" href="/apple-icon-60x60.png">
    <link rel="apple-touch-icon" sizes="72x72" href="/apple-icon-72x72.png">
    <link rel="apple-touch-icon" sizes="76x76" href="/apple-icon-76x76.png">
    <link rel="apple-touch-icon" sizes="114x114" href="/apple-icon-114x114.png">
    <link rel="apple-touch-icon" sizes="120x120" href="/apple-icon-120x120.png">
    <link rel="apple-touch-icon" sizes="144x144" href="/apple-icon-144x144.png">
    <link rel="apple-touch-icon" sizes="152x152" href="/apple-icon-152x152.png">
    <link rel="apple-touch-icon" sizes="180x180" href="/apple-icon-180x180.png">
    <link rel="icon" type="image/png" href="/favicon-32x32.png" sizes="32x32">
    <link rel="icon" type="image/png" href="/android-chrome-192x192.png" sizes="192x192">
    <link rel="icon" type="image/png" href="/favicon-96x96.png" sizes="96x96">
    <link rel="icon" type="image/png" href="/favicon-16x16.png" sizes="16x16">
    <link rel="manifest" href="/manifest.json">
    <meta name="apple-mobile-web-app-title" content="Elastic">
    <meta name="application-name" content="Elastic">
    <meta name="msapplication-TileColor" content="#ffffff">
    <meta name="msapplication-TileImage" content="/mstile-144x144.png">
    <meta name="theme-color" content="#ffffff">
    <meta name="naver-site-verification" content="936882c1853b701b3cef3721758d80535413dbfd">
    <meta name="yandex-verification" content="d8a47e95d0972434">
    <meta name="localized" content="true">
    <meta name="st:robots" content="follow,index">
    <meta property="og:image" content="https://www.elastic.co/static/images/elastic-logo-200.png">
    <link rel="shortcut icon" href="/favicon.ico" type="image/x-icon">
    <link rel="icon" href="/favicon.ico" type="image/x-icon">
    <link rel="apple-touch-icon-precomposed" sizes="64x64" href="/favicon_64x64_16bit.png">
    <link rel="apple-touch-icon-precomposed" sizes="32x32" href="/favicon_32x32.png">
    <link rel="apple-touch-icon-precomposed" sizes="16x16" href="/favicon_16x16.png">
    <!-- Give IE8 a fighting chance -->
    <!--[if lt IE 9]>
    <script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
    <script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
    <![endif]-->
    <link rel="stylesheet" type="text/css" href="/guide/static/styles.css">
  </head>

  <!--© 2015-2021 Elasticsearch B.V. Copying, publishing and/or distributing without written permission is strictly prohibited.-->

  <body>
    <!-- Google Tag Manager -->
    <script>dataLayer = [];</script><noscript><iframe src="//www.googletagmanager.com/ns.html?id=GTM-58RLH5" height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>
    <script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start': new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0], j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src= '//www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f); })(window,document,'script','dataLayer','GTM-58RLH5');</script>
    <!-- End Google Tag Manager -->

    <!-- Global site tag (gtag.js) - Google Analytics -->
    <script async src="https://www.googletagmanager.com/gtag/js?id=UA-12395217-16"></script>
    <script>
      window.dataLayer = window.dataLayer || [];
      function gtag(){dataLayer.push(arguments);}
      gtag('js', new Date());
      gtag('config', 'UA-12395217-16');
    </script>

    <!--BEGIN QUALTRICS WEBSITE FEEDBACK SNIPPET-->
    <script type="text/javascript">
      (function(){var g=function(e,h,f,g){
      this.get=function(a){for(var a=a+"=",c=document.cookie.split(";"),b=0,e=c.length;b<e;b++){for(var d=c[b];" "==d.charAt(0);)d=d.substring(1,d.length);if(0==d.indexOf(a))return d.substring(a.length,d.length)}return null};
      this.set=function(a,c){var b="",b=new Date;b.setTime(b.getTime()+6048E5);b="; expires="+b.toGMTString();document.cookie=a+"="+c+b+"; path=/; "};
      this.check=function(){var a=this.get(f);if(a)a=a.split(":");else if(100!=e)"v"==h&&(e=Math.random()>=e/100?0:100),a=[h,e,0],this.set(f,a.join(":"));else return!0;var c=a[1];if(100==c)return!0;switch(a[0]){case "v":return!1;case "r":return c=a[2]%Math.floor(100/c),a[2]++,this.set(f,a.join(":")),!c}return!0};
      this.go=function(){if(this.check()){var a=document.createElement("script");a.type="text/javascript";a.src=g;document.body&&document.body.appendChild(a)}};
      this.start=function(){var a=this;window.addEventListener?window.addEventListener("load",function(){a.go()},!1):window.attachEvent&&window.attachEvent("onload",function(){a.go()})}};
      try{(new g(100,"r","QSI_S_ZN_emkP0oSe9Qrn7kF","https://znemkp0ose9qrn7kf-elastic.siteintercept.qualtrics.com/WRSiteInterceptEngine/?Q_ZID=ZN_emkP0oSe9Qrn7kF")).start()}catch(i){}})();
    </script><div id="ZN_emkP0oSe9Qrn7kF"><!--DO NOT REMOVE-CONTENTS PLACED HERE--></div>
    <!--END WEBSITE FEEDBACK SNIPPET-->

    <div id="elastic-nav" style="display:none;"></div>
    <script src="https://www.elastic.co/elastic-nav.js"></script>

    <!-- Subnav -->
    <div>
      <div>
        <div class="tertiary-nav d-none d-md-block">
          <div class="container">
            <div class="p-t-b-15 d-flex justify-content-between nav-container">
              <div class="breadcrum-wrapper"><span><a href="/guide/" style="font-size: 14px; font-weight: 600; color: #000;">Docs</a></span></div>
            </div>
          </div>
        </div>
      </div>
    </div>

    <div class="main-container">
      <section id="content">
        <div class="content-wrapper">

          <section id="guide" lang="en">
            <div class="container">
              <div class="row">
                <div class="col-xs-12 col-sm-8 col-md-8 guide-section">
                  <!-- start body -->
                  <div class="page_header">
<strong>IMPORTANT</strong>: No additional bug fixes or documentation updates
will be released for this version. For the latest information, see the
<a href="../current/index.html">current release documentation</a>.
</div>
<div id="content">
<div class="breadcrumbs">
<span class="breadcrumb-link"><a href="index.html">Elasticsearch Guide [7.7]</a></span>
»
<span class="breadcrumb-link"><a href="secure-cluster.html">Secure a cluster</a></span>
»
<span class="breadcrumb-link"><a href="saml-guide.html">Configuring SAML single-sign-on on the Elastic Stack</a></span>
»
<span class="breadcrumb-node">SAML without Kibana</span>
</div>
<div class="navheader">
<span class="prev">
<a href="saml-troubleshooting.html">« Troubleshooting SAML Realm Configuration</a>
</span>
<span class="next">
<a href="oidc-guide.html">Configuring single sign-on to the Elastic Stack using OpenID Connect »</a>
</span>
</div>
<div class="section">
<div class="titlepage"><div><div>
<h2 class="title">
<a id="saml-no-kibana"></a>SAML without Kibana<a class="edit_me edit_me_private" rel="nofollow" title="Editing on GitHub is available to Elastic" href="https://github.com/elastic/elasticsearch/edit/7.7/x-pack/docs/en/security/authentication/saml-guide.asciidoc">edit</a>
</h2>
</div></div></div>
<p>The SAML realm in Elasticsearch is designed to allow users to authenticate to Kibana and as
such, most of the parts of the guide above make the assumption that Kibana is used.
This section describes how a custom web application could use the relevant SAML
REST APIs in order to authenticate the users to Elasticsearch with SAML.</p>
<div class="note admon">
<div class="icon"></div>
<div class="admon_content">
<p>This section assumes that the reader is familiar with the SAML 2.0 standard
and more specifically with the SAML 2.0 Web Browser Single Sign On profile.</p>
</div>
</div>
<p>Single sign-on realms such as OpenID Connect and SAML make use of the Token Service in
Elasticsearch and in principle exchange a SAML or OpenID Connect Authentication response for
an Elasticsearch access token and a refresh token. The access token is used as credentials
for subsequent calls to Elasticsearch. The refresh token enables the user to get new Elasticsearch
access tokens after the current one expires.</p>
<div class="section">
<div class="titlepage"><div><div>
<h3 class="title">
<a id="saml-no-kibana-realm"></a>SAML realm<a class="edit_me edit_me_private" rel="nofollow" title="Editing on GitHub is available to Elastic" href="https://github.com/elastic/elasticsearch/edit/7.7/x-pack/docs/en/security/authentication/saml-guide.asciidoc">edit</a>
</h3>
</div></div></div>
<p>You must create a SAML realm and configure it accordingly
in Elasticsearch. See <a class="xref" href="saml-guide-authentication.html" title="Configure Elasticsearch for SAML authentication">Configure Elasticsearch for SAML authentication</a></p>
</div>

<div class="section">
<div class="titlepage"><div><div>
<h3 class="title">
<a id="saml-no-kibana-user"></a>Service Account user for accessing the APIs<a class="edit_me edit_me_private" rel="nofollow" title="Editing on GitHub is available to Elastic" href="https://github.com/elastic/elasticsearch/edit/7.7/x-pack/docs/en/security/authentication/saml-guide.asciidoc">edit</a>
</h3>
</div></div></div>
<p>The realm is designed with the assumption that there needs to be a privileged entity
acting as an authentication proxy. In this case, the custom web application is the
authentication proxy handling the authentication of end users ( more correctly,
"delegating" the authentication to the SAML Identity Provider ). The SAML related
APIs require authentication and the necessary authorization level for the authenticated
user. For this reason, you must create a Service Account user and assign it a role
that gives it the <code class="literal">manage_saml</code> cluster privilege. The use of the <code class="literal">manage_token</code>
cluster privilege will be necessary after the authentication takes place, so that the
the service account user can maintain access in order refresh access tokens on
behalf of the authenticated users or to subsequently log them out.</p>
<div class="pre_wrapper lang-console">
<pre class="programlisting prettyprint lang-console">POST /_security/role/saml-service-role
{
  "cluster" : ["manage_saml", "manage_token"]
}</pre>
</div>
<div class="console_widget" data-snippet="snippets/1228.console"></div>
<div class="pre_wrapper lang-console">
<pre class="programlisting prettyprint lang-console">POST /_security/user/saml-service-user
{
  "password" : "&lt;somePasswordHere&gt;",
  "roles"    : ["saml-service-role"]
}</pre>
</div>
<div class="console_widget" data-snippet="snippets/1229.console"></div>
</div>

<div class="section">
<div class="titlepage"><div><div>
<h3 class="title">
<a id="saml-no-kibana-sp-init-sso"></a>Handling the SP-initiated authentication flow<a class="edit_me edit_me_private" rel="nofollow" title="Editing on GitHub is available to Elastic" href="https://github.com/elastic/elasticsearch/edit/7.7/x-pack/docs/en/security/authentication/saml-guide.asciidoc">edit</a>
</h3>
</div></div></div>
<p>On a high level, the custom web application would need to perform the
following steps in order to authenticate a user with SAML against Elasticsearch:</p>
<div class="olist orderedlist">
<ol class="orderedlist">
<li class="listitem">
<p>Make an HTTP POST request to <code class="literal">_security/saml/prepare</code>, authenticating as
the <code class="literal">saml-service-user</code> user. Use either the name of the SAML realm in the Elasticsearch configuration or the value for
the Assertion Consumer Service URL in the request body.
See the <a class="xref" href="security-api-saml-prepare-authentication.html" title="SAML prepare authentication API">SAML prepare authentication API</a> for more details.</p>
<div class="pre_wrapper lang-console">
<pre class="programlisting prettyprint lang-console">POST /_security/saml/prepare
{
  "realm" : "saml1"
}</pre>
</div>
<div class="console_widget" data-snippet="snippets/1230.console"></div>
</li>
<li class="listitem">
Handle the response from <code class="literal">/_security/saml/prepare</code>. The response from Elasticsearch will contain 3 parameters:
  <code class="literal">redirect</code>, <code class="literal">realm</code> and <code class="literal">id</code>. The custom web application would need to store the value for <code class="literal">id</code>
 in the user’s session (client side in a cookie or server side if session information is
persisted this way). It must also redirect the user’s browser to the URL that  was returned in the
  <code class="literal">redirect</code> parameter. The <code class="literal">id</code> value should not be disregarded as it is used as a nonce in SAML in
order to mitigate against replay attacks.
</li>
<li class="listitem">
<p>Handle a subsequent response from the SAML IdP. After the user is successfully authenticated with the
Identity Provider they will be redirected back to the Assertion Consumer Service URL. This <code class="literal">sp.acs</code> needs to be
defined as a URL which the custom web application handles. When it receives this HTTP POST request, the
custom web application must parse it and make an HTTP POST request itself to the
<code class="literal">_security/saml/authenticate</code> API. It must authenticate as the <code class="literal">saml-service-user</code> user and pass
the Base64 encoded SAML Response that was sent as the body of the request. It must also pass the value for <code class="literal">id</code> that it had saved in the user’s session previously.</p>
<p>See <a class="xref" href="security-api-saml-authenticate.html" title="SAML authenticate API">SAML authenticate API</a> for more details.</p>
<div class="pre_wrapper lang-console">
<pre class="programlisting prettyprint lang-console">POST /_security/saml/authenticate
{
  "content" : "PHNhbWxwOlJlc3BvbnNlIHhtbG5zOnNhbWxwPSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6cHJvdG9jb2wiIHhtbG5zOnNhbWw9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMD.....",
  "ids" : ["4fee3b046395c4e751011e97f8900b5273d56685"]
}</pre>
</div>
<div class="console_widget" data-snippet="snippets/1231.console"></div>
<p>Elasticsearch will validate this and if all is correct will respond with an access token that can be used
as a <code class="literal">Bearer</code> token for subsequent requests. It also supplies a refresh token that can be later used to refresh the given
access token as described in <a class="xref" href="security-api-get-token.html" title="Get token API">get token API</a>.</p>
</li>
<li class="listitem">
The response to calling <code class="literal">/_security/saml/authenticate</code> will contain only the username of the authenticated
user. If you need to get the values for the SAML Attributes that were contained in the SAML
Response for that user, you can call the Authenticate API <code class="literal">/_security/_authenticate/</code> using the access token as a <code class="literal">Bearer</code> token
and the SAML attribute values will be contained in the response as part of the <a class="xref" href="saml-user-metadata.html" title="User metadata">User metadata</a>.
</li>
</ol>
</div>
</div>

<div class="section">
<div class="titlepage"><div><div>
<h3 class="title">
<a id="saml-no-kibana-idp-init-sso"></a>Handling the IdP-initiated authentication flow<a class="edit_me edit_me_private" rel="nofollow" title="Editing on GitHub is available to Elastic" href="https://github.com/elastic/elasticsearch/edit/7.7/x-pack/docs/en/security/authentication/saml-guide.asciidoc">edit</a>
</h3>
</div></div></div>
<p>Elasticsearch can also handle the IdP-initiated Single Sign On flow of the SAML 2 Web Browser SSO profile. In this
case the authentication starts with an unsolicited authentication response from the SAML Identity
Provider. The difference with the <a class="xref" href="saml-no-kibana.html#saml-no-kibana-sp-init-sso" title="Handling the SP-initiated authentication flow">SP initiated SSO</a> is that the web application needs to handle
requests to the <code class="literal">sp.acs</code> that will not come as responses to previous redirections. As such, it will not have a session
for the user already, and it will not have any stored values for the <code class="literal">id</code> parameter. The request to the
<code class="literal">_security/saml/authenticate</code> API will look like the one below in this case:</p>
<div class="pre_wrapper lang-console">
<pre class="programlisting prettyprint lang-console">POST /_security/saml/authenticate
{
  "content" : "PHNhbWxwOlJlc3BvbnNlIHhtbG5zOnNhbWxwPSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6cHJvdG9jb2wiIHhtbG5zOnNhbWw9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMD.....",
  "ids" : []
}</pre>
</div>
<div class="console_widget" data-snippet="snippets/1232.console"></div>
</div>

<div class="section">
<div class="titlepage"><div><div>
<h3 class="title">
<a id="saml-no-kibana-slo"></a>Handling the logout flow<a class="edit_me edit_me_private" rel="nofollow" title="Editing on GitHub is available to Elastic" href="https://github.com/elastic/elasticsearch/edit/7.7/x-pack/docs/en/security/authentication/saml-guide.asciidoc">edit</a>
</h3>
</div></div></div>
<div class="olist orderedlist">
<ol class="orderedlist">
<li class="listitem">
<p>At some point, if necessary, the custom web application can log the user out by using the
<a class="xref" href="security-api-saml-logout.html" title="SAML logout API">SAML logout API</a> and passing the access token and refresh token as parameters. For example:</p>
<div class="pre_wrapper lang-console">
<pre class="programlisting prettyprint lang-console">POST /_security/saml/logout
{
  "token" : "46ToAxZVaXVVZTVKOVF5YU04ZFJVUDVSZlV3",
  "refresh_token": "mJdXLtmvTUSpoLwMvdBt_w"
}</pre>
</div>
<div class="console_widget" data-snippet="snippets/1233.console"></div>
<p>If the SAML realm is configured accordingly and the IdP supports it (see <a class="xref" href="saml-guide-authentication.html#saml-logout" title="SAML logout">SAML logout</a>), this request will trigger a SAML
SP-initiated Single Logout. In this case, the response will include a <code class="literal">redirect</code>
parameter indicating where the user needs to be redirected at the IdP in order to complete the logout.</p>
</li>
<li class="listitem">
<p>Alternatively, the IdP might initiate the Single Logout flow at some point. In order to handle this,
the Logout URL (<code class="literal">sp.logout</code>) needs to be handled by the custom web app. The query part of the URL that the
user will be redirected to will contain a SAML Logout request and this query part needs to be relayed to Elasticsearch
using the <a class="xref" href="security-api-saml-invalidate.html" title="SAML invalidate API">SAML invalidate API</a></p>
<div class="pre_wrapper lang-console">
<pre class="programlisting prettyprint lang-console">POST /_security/saml/invalidate
{
  "query" : "SAMLRequest=nZFda4MwFIb%2FiuS%2BmviRpqFaClKQdbvo2g12M2KMraCJ9cRR9utnW4Wyi13sMie873MeznJ1aWrnS3VQGR0j4mLkKC1NUeljjA77zYyhVbIE0dR%2By7fmaHq7U%2BdegXWGpAZ%2B%2F4pR32luBFTAtWgUcCv56%2Fp5y30X87Yz1khTIycdgpUW9kY7WdsC9zxoXTvMvWuVV98YyMnSGH2SYE5pwALBIr9QKiwDGpW0oGVUznGeMyJZKFkQ4jBf5HnhUymjIhzCAL3KNFihbYx8TBYzzGaY7EnIyZwHzCWMfiDnbRIftkSjJr%2BFu0e9v%2B0EgOquRiiZjKpiVFp6j50T4WXoyNJ%2FEWC9fdqc1t%2F1%2B2F3aUpjzhPiXpqMz1%2FHSn4A&amp;SigAlg=http%3A%2F%2Fwww.w3.org%2F2001%2F04%2Fxmldsig-more%23rsa-sha256&amp;Signature=MsAYz2NFdovMG2mXf6TSpu5vlQQyEJAg%2B4KCwBqJTmrb3yGXKUtIgvjqf88eCAK32v3eN8vupjPC8LglYmke1ZnjK0%2FKxzkvSjTVA7mMQe2AQdKbkyC038zzRq%2FYHcjFDE%2Bz0qISwSHZY2NyLePmwU7SexEXnIz37jKC6NMEhus%3D",
  "realm" : "saml1"
}</pre>
</div>
<div class="console_widget" data-snippet="snippets/1234.console"></div>
<p>The custom web application will then need to also handle the response, which will include a <code class="literal">redirect</code>
parameter with a URL in the IdP that contains the SAML Logout response. The application should redirect the user
there to complete the logout.</p>
</li>
</ol>
</div>
</div>

</div>
<div class="navfooter">
<span class="prev">
<a href="saml-troubleshooting.html">« Troubleshooting SAML Realm Configuration</a>
</span>
<span class="next">
<a href="oidc-guide.html">Configuring single sign-on to the Elastic Stack using OpenID Connect »</a>
</span>
</div>
</div>

                  <!-- end body -->
                </div>
                <div class="col-xs-12 col-sm-4 col-md-4" id="right_col">
                  <div id="rtpcontainer" style="display: block;">
                    <div class="mktg-promo">
                      <h3>Most Popular</h3>
                      <ul class="icons">
                        <li class="icon-elasticsearch-white"><a href="https://www.elastic.co/webinars/getting-started-elasticsearch?baymax=default&amp;elektra=docs&amp;storm=top-video">Get Started with Elasticsearch: Video</a></li>
                        <li class="icon-kibana-white"><a href="https://www.elastic.co/webinars/getting-started-kibana?baymax=default&amp;elektra=docs&amp;storm=top-video">Intro to Kibana: Video</a></li>
                        <li class="icon-logstash-white"><a href="https://www.elastic.co/webinars/introduction-elk-stack?baymax=default&amp;elektra=docs&amp;storm=top-video">ELK for Logs &amp; Metrics: Video</a></li>
                      </ul>
                    </div>
                  </div>
                </div>
              </div>
            </div>
          </section>

        </div>


<div id="elastic-footer"></div>
<script src="https://www.elastic.co/elastic-footer.js"></script>
<!-- Footer Section end-->

      </section>
    </div>

<script src="/guide/static/jquery.js"></script>
<script type="text/javascript" src="/guide/static/docs.js"></script>
<script type="text/javascript">
  window.initial_state = {}</script>
  </body>
</html>
